//#include "log.h"
//#include <cassert>
//#include <vector>
//#include <string>
//#include "vulkan_wrapper.h"
//#define STB_IMAGE_IMPLEMENTATION
//#define STBI_ONLY_PNG
//#include <stb/stb_image.h>
//#include "CreateShaderModule.h"
//#include "VulkanMain.hpp"
//
//// Android log function wrappers
//static const char* kTAG = "Vulkan-Tutorial06";
//#define LOGI(...) \
//  ((void)__android_log_print(ANDROID_LOG_INFO, kTAG, __VA_ARGS__))
//#define LOGW(...) \
//  ((void)__android_log_print(ANDROID_LOG_WARN, kTAG, __VA_ARGS__))
//#define LOGE(...) \
//  ((void)__android_log_print(ANDROID_LOG_ERROR, kTAG, __VA_ARGS__))
//
//// Vulkan call wrapper
//#define CALL_VK(func)                                                 \
//  if (VK_SUCCESS != (func)) {                                         \
//    __android_log_print(ANDROID_LOG_ERROR, "Tutorial ",               \
//                        "Vulkan error. File[%s], line[%d]", __FILE__, \
//                        __LINE__);                                    \
//    assert(false);                                                    \
//  }
//
//// A macro to check value is VK_SUCCESS
//// Used also for non-vulkan functions but return VK_SUCCESS
//#define VK_CHECK(x) CALL_VK(x)
//
//
//// Global Variables ...
//struct VulkanDeviceInfo {
//  bool initialized_;
//
//  VkInstance instance_;
//  VkPhysicalDevice gpuDevice_;
//  VkPhysicalDeviceMemoryProperties gpuMemoryProperties_;
//  VkDevice device_;
//  uint32_t queueFamilyIndex_;
//
//  VkSurfaceKHR surface_;
//  VkQueue queue_;
//};
//VulkanDeviceInfo device;
//
//
//struct VulkanSwapchainInfo {
//  VkSwapchainKHR swapchain_;
//  uint32_t swapchainLength_;
//
//  VkExtent2D displaySize_;
//  VkFormat displayFormat_;
//
//  // array of frame buffers and views
//  VkFramebuffer* framebuffers_;
//  VkImage* displayImages_;
//  VkImageView* displayViews_;
//};
//VulkanSwapchainInfo swapchain;
//
//typedef struct texture_object {
//  VkSampler sampler;
//  VkImage image;
//  VkImageLayout imageLayout;
//  VkDeviceMemory mem;
//  VkImageView view;
//  int32_t tex_width;
//  int32_t tex_height;
//} texture_object;
//static const VkFormat kTexFmt = VK_FORMAT_R8G8B8A8_UNORM;
//#define TUTORIAL_TEXTURE_COUNT 1
//const char* texFiles[TUTORIAL_TEXTURE_COUNT] = {
//    "sample_tex_2.png",
//};
//struct texture_object textures[TUTORIAL_TEXTURE_COUNT];
//
//// struct VulkanBufferInfo {
////   VkBuffer vertexBuf_;
//// };
//struct VulkanBufferInfo {
//  VkBuffer vertexBuf_;
//  VkDeviceMemory memory_;
//  void* mappedData_;  // 用于动态更新顶点数据
//};
//
//VulkanBufferInfo buffers;
//
//struct VulkanGfxPipelineInfo {
//  VkDescriptorSetLayout dscLayout_;
//  VkDescriptorPool descPool_;
//  VkDescriptorSet descSet_;
//  VkPipelineLayout layout_;
//  VkPipelineCache cache_;
//  VkPipeline pipeline_;
//};
//VulkanGfxPipelineInfo gfxPipeline;
//
//struct VulkanRenderInfo {
//  VkRenderPass renderPass_;
//  VkCommandPool cmdPool_;
//  VkCommandBuffer* cmdBuffer_;
//  uint32_t cmdBufferLen_;
//  VkSemaphore semaphore_;
//  VkFence fence_;
//  
//  // 测试用资源
//  VkBuffer testIndexBuffer_;
//  VkDeviceMemory testIndexMemory_;
//  VkBuffer testCopyBuffer_;
//  VkDeviceMemory testCopyMemory_;
//  VkImage testImage_;
//  VkDeviceMemory testImageMemory_;
//  VkEvent testEvent_;
//  
//  // 时间戳查询池
//  VkQueryPool testQueryPool_;
//
//  VkPipeline testComputePipeline_;
//  VkPipelineLayout testComputePipelineLayout_;
//  VkDescriptorUpdateTemplate testDescriptorUpdateTemplate_;
//  VkPrivateDataSlot testPrivateDataSlot_;
//  VkRenderPass testRenderPass2_;
//  VkSamplerYcbcrConversion testYcbcrConversion_;
//  VkShaderModule testComputeShaderModule_;
//
//  // 间接绘制相关资源
//  VkBuffer testIndirectBuffer_;
//  VkDeviceMemory testIndirectMemory_;
//  VkBuffer testCountBuffer_;
//  VkDeviceMemory testCountMemory_;
//};
//VulkanRenderInfo render;
//
//// 更完整的扩展映射表
//struct VulkanFeatureExtensionMap {
//  const char* featureName;
//  const char* extensionName;
//  uint32_t vulkanCoreVersion; // 该功能成为核心功能的版本
//  bool isKHR; // 是否为 KHR 扩展
//};
//
//
//// 创建简单的计算着色器SPIR-V字节码
//static const uint32_t simpleComputeShaderCode[] = {
//  0x07230203, 0x00010000, 0x00080006, 0x0000001c, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
//  0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
//  0x0005000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060010, 0x00000004, 0x00000011,
//  0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004,
//  0x6e69616d, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00050036,
//  0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x000100fd, 0x00010038
//};
//
//VkShaderModule CreateSimpleComputeShader() {
//  VkShaderModuleCreateInfo createInfo{
//      .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .codeSize = sizeof(simpleComputeShaderCode),
//      .pCode = simpleComputeShaderCode
//  };
//  
//  VkShaderModule shaderModule;
//  VkResult result = vkCreateShaderModule(device.device_, &createInfo, nullptr, &shaderModule);
//  if (result == VK_SUCCESS) {
//      LOGI("Simple compute shader created successfully");
//      return shaderModule;
//  } else {
//      LOGE("Failed to create compute shader: %d", result);
//      return VK_NULL_HANDLE;
//  }
//}
//
//// ====================
//
//// Android Native App pointer...
//android_app* androidAppCtx = nullptr;
//void setImageLayout(VkCommandBuffer cmdBuffer, VkImage image,
//                    VkImageLayout oldImageLayout, VkImageLayout newImageLayout,
//                    VkPipelineStageFlags srcStages,
//                    VkPipelineStageFlags destStages);
//
//// Create vulkan device
//void CreateVulkanDevice(ANativeWindow* platformWindow,
//                        VkApplicationInfo* appInfo) {
//  std::vector<const char*> instance_extensions;
//  std::vector<const char*> device_extensions;
//  
//  // 必需的实例扩展
//  instance_extensions.push_back("VK_KHR_surface");
//  instance_extensions.push_back("VK_KHR_android_surface");
//
//  // 检查并添加可选的实例扩展
//  uint32_t availableExtensionCount = 0;
//  vkEnumerateInstanceExtensionProperties(nullptr, &availableExtensionCount, nullptr);
//  std::vector<VkExtensionProperties> availableExtensions(availableExtensionCount);
//  vkEnumerateInstanceExtensionProperties(nullptr, &availableExtensionCount, availableExtensions.data());
//  
//  LOGI("=== Checking Available Instance Extensions ===");
//  
//  // 检查 VK_KHR_get_surface_capabilities2
//  bool hasSurfaceCapabilities2 = false;
//  for (const auto& ext : availableExtensions) {
//    if (strcmp(ext.extensionName, "VK_KHR_get_surface_capabilities2") == 0) {
//      hasSurfaceCapabilities2 = true;
//      instance_extensions.push_back("VK_KHR_get_surface_capabilities2");
//      LOGI("Added instance extension: VK_KHR_get_surface_capabilities2");
//      break;
//    }
//  }
//  
//  if (!hasSurfaceCapabilities2) {
//    LOGI("VK_KHR_get_surface_capabilities2 not available");
//  }
//  
//  // 尝试添加 display 相关扩展
//  bool hasDisplayExt = false;
//  bool hasDisplaySwapchainExt = false;
//
//  // 检查其他有用的实例扩展
//  for (const auto& ext : availableExtensions) {
//    // 检查 VK_KHR_display
//    if (strcmp(ext.extensionName, "VK_KHR_display") == 0) {
//      hasDisplayExt = true;
//      instance_extensions.push_back("VK_KHR_display");
//      LOGI("Added instance extension: VK_KHR_display");
//    }
//    // 添加 get_physical_device_properties2 如果可用
//    else if (strcmp(ext.extensionName, "VK_KHR_get_physical_device_properties2") == 0) {
//      instance_extensions.push_back("VK_KHR_get_physical_device_properties2");
//      LOGI("Added instance extension: VK_KHR_get_physical_device_properties2");
//    }
//    // 添加 external_memory_capabilities 如果可用
//    else if (strcmp(ext.extensionName, "VK_KHR_external_memory_capabilities") == 0) {
//      instance_extensions.push_back("VK_KHR_external_memory_capabilities");
//      LOGI("Added instance extension: VK_KHR_external_memory_capabilities");
//    }
//    // 添加 external_fence_capabilities 如果可用
//    else if (strcmp(ext.extensionName, "VK_KHR_external_fence_capabilities") == 0) {
//      instance_extensions.push_back("VK_KHR_external_fence_capabilities");
//      LOGI("Added instance extension: VK_KHR_external_fence_capabilities");
//    }
//    // 添加 external_semaphore_capabilities 如果可用
//    else if (strcmp(ext.extensionName, "VK_KHR_external_semaphore_capabilities") == 0) {
//      instance_extensions.push_back("VK_KHR_external_semaphore_capabilities");
//      LOGI("Added instance extension: VK_KHR_external_semaphore_capabilities");
//    }
//  }
//
//  if (!hasDisplayExt) {
//    LOGE("VK_KHR_display not available on this device (normal for Android)");
//  }
//
//  
//  LOGI("Total instance extensions to enable: %zu", instance_extensions.size());
//  for (size_t i = 0; i < instance_extensions.size(); i++) {
//    LOGI("  [%zu] %s", i, instance_extensions[i]);
//  }
//  
//  // 设备扩展
//  device_extensions.push_back("VK_KHR_swapchain");
//
//  // **********************************************************
//  // Create the Vulkan instance with enabled extensions
//  VkInstanceCreateInfo instanceCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
//      .pNext = nullptr,
//      .pApplicationInfo = appInfo,
//      .enabledLayerCount = 0,
//      .ppEnabledLayerNames = nullptr,
//      .enabledExtensionCount = static_cast<uint32_t>(instance_extensions.size()),
//      .ppEnabledExtensionNames = instance_extensions.data(),
//  };
//  CALL_VK(vkCreateInstance(&instanceCreateInfo, nullptr, &device.instance_));
//  
//  LOGI("Vulkan instance created successfully with %zu extensions", instance_extensions.size());
//  
//  // 验证扩展函数是否可用
//  if (hasSurfaceCapabilities2) {
//    PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR test_func = 
//        (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)vkGetInstanceProcAddr(device.instance_, "vkGetPhysicalDeviceSurfaceCapabilities2KHR");
//    
//    if (test_func) {
//      LOGI("vkGetPhysicalDeviceSurfaceCapabilities2KHR function pointer obtained successfully");
//    } else {
//      LOGI("Failed to get vkGetPhysicalDeviceSurfaceCapabilities2KHR function pointer");
//    }
//    
//    PFN_vkGetPhysicalDeviceSurfaceFormats2KHR test_func2 = 
//        (PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)vkGetInstanceProcAddr(device.instance_, "vkGetPhysicalDeviceSurfaceFormats2KHR");
//    
//    if (test_func2) {
//      LOGI("vkGetPhysicalDeviceSurfaceFormats2KHR function pointer obtained successfully");
//    } else {
//      LOGI("Failed to get vkGetPhysicalDeviceSurfaceFormats2KHR function pointer");
//    }
//  }
//  
//  // ========== 测试 vkEnumeratePhysicalDeviceGroups ==========
//  LOGI("Testing vkEnumeratePhysicalDeviceGroups...");
//  uint32_t deviceGroupCount = 0;
//  VkResult groupResult = vkEnumeratePhysicalDeviceGroups(device.instance_, &deviceGroupCount, nullptr);
//  if (groupResult == VK_SUCCESS) {
//    if (deviceGroupCount > 0) {
//      std::vector<VkPhysicalDeviceGroupProperties> deviceGroups(deviceGroupCount);
//      for (auto& group : deviceGroups) {
//        group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
//        group.pNext = nullptr;
//      }
//      
//      VkResult enumResult = vkEnumeratePhysicalDeviceGroups(device.instance_, &deviceGroupCount, deviceGroups.data());
//      if (enumResult == VK_SUCCESS) {
//        LOGI("vkEnumeratePhysicalDeviceGroups: SUCCESS - found %d device groups", deviceGroupCount);
//        for (uint32_t i = 0; i < deviceGroupCount; i++) {
//          LOGI("  Group %d: %d physical devices, subset allocation: %s", 
//               i, deviceGroups[i].physicalDeviceCount,
//               deviceGroups[i].subsetAllocation ? "YES" : "NO");
//        }
//      } else {
//        LOGI("vkEnumeratePhysicalDeviceGroups: Enumeration failed (%d)", enumResult);
//      }
//    } else {
//      LOGI("vkEnumeratePhysicalDeviceGroups: SUCCESS - no device groups found");
//    }
//  } else {
//    LOGI("vkEnumeratePhysicalDeviceGroups: Failed (%d)", groupResult);
//  }
//  
//  VkAndroidSurfaceCreateInfoKHR createInfo{
//      .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
//      .pNext = nullptr,
//      .flags = 0,
//      .window = platformWindow
//  };
//
//  CALL_VK(vkCreateAndroidSurfaceKHR(device.instance_, &createInfo, nullptr,
//                                    &device.surface_));
//                                    
//  // Find one GPU to use:
//  uint32_t gpuCount = 0;
//  CALL_VK(vkEnumeratePhysicalDevices(device.instance_, &gpuCount, nullptr));
//  VkPhysicalDevice tmpGpus[gpuCount];
//  CALL_VK(vkEnumeratePhysicalDevices(device.instance_, &gpuCount, tmpGpus));
//  device.gpuDevice_ = tmpGpus[0];  // Pick up the first GPU Device
//
//  vkGetPhysicalDeviceMemoryProperties(device.gpuDevice_,
//                                     &device.gpuMemoryProperties_);
//
//  // Find a GFX queue family
//  uint32_t queueFamilyCount;
//  vkGetPhysicalDeviceQueueFamilyProperties(device.gpuDevice_, &queueFamilyCount,
//                                           nullptr);
//  assert(queueFamilyCount);
//  std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount);
//  vkGetPhysicalDeviceQueueFamilyProperties(device.gpuDevice_, &queueFamilyCount,
//                                           queueFamilyProperties.data());
//
//  uint32_t queueFamilyIndex;
//  for (queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount;
//       queueFamilyIndex++) {
//    if (queueFamilyProperties[queueFamilyIndex].queueFlags &
//        VK_QUEUE_GRAPHICS_BIT) {
//      break;
//    }
//  }
//  assert(queueFamilyIndex < queueFamilyCount);
//  device.queueFamilyIndex_ = queueFamilyIndex;
//  
//  // Create a logical device (vulkan device)
//  float priorities[] = {
//      1.0f,
//  };
//  VkDeviceQueueCreateInfo queueCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .queueFamilyIndex = device.queueFamilyIndex_,
//      .queueCount = 1,
//      .pQueuePriorities = priorities,
//  };
//
//  // 查询设备支持的功能
//  VkPhysicalDeviceFeatures availableFeatures;
//  vkGetPhysicalDeviceFeatures(device.gpuDevice_, &availableFeatures);
//
//  // 查询Vulkan 1.3功能
//  VkPhysicalDeviceVulkan13Features vulkan13Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
//      .pNext = nullptr
//  };
//
//  VkPhysicalDeviceVulkan12Features vulkan12Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
//      .pNext = &vulkan13Features
//  };
//
//  VkPhysicalDeviceVulkan11Features vulkan11Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
//      .pNext = &vulkan12Features
//  };
//
//  VkPhysicalDeviceFeatures2 deviceFeatures2{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
//      .pNext = &vulkan11Features,
//      .features = {}
//  };
//
//  // 首先查询设备支持的功能
//  vkGetPhysicalDeviceFeatures2(device.gpuDevice_, &deviceFeatures2);
//
//  // 记录查询到的功能状态
//  LOGI("=== Device Feature Query Results ===");
//  LOGI("privateData supported: %s", vulkan13Features.privateData ? "YES" : "NO");
//  LOGI("synchronization2 supported: %s", vulkan13Features.synchronization2 ? "YES" : "NO");
//  LOGI("dynamicRendering supported: %s", vulkan13Features.dynamicRendering ? "YES" : "NO");
//  LOGI("timelineSemaphore supported: %s", vulkan12Features.timelineSemaphore ? "YES" : "NO");
//  LOGI("bufferDeviceAddress supported: %s", vulkan12Features.bufferDeviceAddress ? "YES" : "NO");
//
//  // 如果privateData不支持，记录详细信息
//  if (!vulkan13Features.privateData) {
//    LOGE("privateData is NOT supported by this device");
//    LOGE("This means the GPU hardware or driver doesn't support private data functionality");
//    LOGE("Private data tests will be skipped, but other Vulkan 1.3 features may still work");
//  }
//
//  // 现在创建要启用的功能结构体（重新初始化，只启用支持的功能）
//  VkPhysicalDeviceVulkan13Features enabledVulkan13Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
//      .pNext = nullptr
//  };
//
//  VkPhysicalDeviceVulkan12Features enabledVulkan12Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
//      .pNext = &enabledVulkan13Features
//  };
//
//  VkPhysicalDeviceVulkan11Features enabledVulkan11Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
//      .pNext = &enabledVulkan12Features
//  };
//
//  VkPhysicalDeviceFeatures2 enabledDeviceFeatures2{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
//      .pNext = &enabledVulkan11Features,
//      .features = {}
//  };
//
//  // 启用基本功能
//  VkPhysicalDeviceFeatures enabledDeviceFeatures{};
//  if (availableFeatures.multiDrawIndirect) {
//    enabledDeviceFeatures.multiDrawIndirect = VK_TRUE;
//    LOGI("Enabling multiDrawIndirect feature");
//  }
//  if (availableFeatures.drawIndirectFirstInstance) {
//    enabledDeviceFeatures.drawIndirectFirstInstance = VK_TRUE;
//    LOGI("Enabling drawIndirectFirstInstance feature");
//  }
//
//  //   // 检查并启用 privateData 功能（强制启用用于测试---->如果不支持则测试时必崩溃，无论多简单的测试）
//  // if (vulkan13Features.privateData) {
//  //     enabledVulkan13Features.privateData = VK_TRUE;
//  //     LOGI("Enabling privateData feature - hardware supports it");
//  // } else {
//  //     // 强制启用进行测试
//  //     enabledVulkan13Features.privateData = VK_TRUE;
//  //     LOGW("FORCING privateData feature despite hardware not reporting support");
//  //     LOGW("This may cause undefined behavior or crashes - for testing only!");
//  // }
//
//  // 检查并启用 privateData 功能（只有在支持的情况下）
//  if (vulkan13Features.privateData) {
//    enabledVulkan13Features.privateData = VK_TRUE;
//    LOGI("Enabling privateData feature - full privateData testing will be available");
//  } else {
//    enabledVulkan13Features.privateData = VK_FALSE;
//    LOGI("privateData feature not supported by device - will be skipped");
//  }
//
//  // 检查并启用其他有用的Vulkan 1.3功能
//  if (vulkan13Features.synchronization2) {
//    enabledVulkan13Features.synchronization2 = VK_TRUE;
//    LOGI("Enabling synchronization2 feature");
//  }
//
//  if (vulkan13Features.dynamicRendering) {
//    enabledVulkan13Features.dynamicRendering = VK_TRUE;
//    LOGI("Enabling dynamicRendering feature");
//  }
//
//  // 启用一些Vulkan 1.2功能
//  if (vulkan12Features.timelineSemaphore) {
//    enabledVulkan12Features.timelineSemaphore = VK_TRUE;
//    LOGI("Enabling timelineSemaphore feature");
//  }
//
//  if (vulkan12Features.bufferDeviceAddress) {
//    enabledVulkan12Features.bufferDeviceAddress = VK_TRUE;
//    LOGI("Enabling bufferDeviceAddress feature");
//  }
//
//  // 将基本功能复制到 Features2 结构体中
//  enabledDeviceFeatures2.features = enabledDeviceFeatures;
//
//  VkDeviceCreateInfo deviceCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
//      .pNext = &enabledDeviceFeatures2,  // 使用启用的功能链
//      .queueCreateInfoCount = 1,
//      .pQueueCreateInfos = &queueCreateInfo,
//      .enabledLayerCount = 0,
//      .ppEnabledLayerNames = nullptr,
//      .enabledExtensionCount = static_cast<uint32_t>(device_extensions.size()),
//      .ppEnabledExtensionNames = device_extensions.data(),
//      .pEnabledFeatures = nullptr,  // 设置为 nullptr，因为我们使用 pNext 链
//  };
//
//  CALL_VK(vkCreateDevice(device.gpuDevice_, &deviceCreateInfo, nullptr, &device.device_));
//  vkGetDeviceQueue(device.device_, 0, 0, &device.queue_);
//
//  // 检查设备扩展（并非实例扩展，得再createDevice后再检查一下）
//  uint32_t deviceExtensionCount = 0;
//  LOGE("=== Checking Available Device Extensions ===");
//  vkEnumerateDeviceExtensionProperties(device.gpuDevice_, nullptr, &deviceExtensionCount, nullptr);
//  LOGE("Available device extensions count: %d", deviceExtensionCount);
//  if (deviceExtensionCount > 0) {
//    std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
//    vkEnumerateDeviceExtensionProperties(device.gpuDevice_, nullptr, &deviceExtensionCount, deviceExtensions.data());
//    
//    for (const auto& ext : deviceExtensions) {
//      // 检查 VK_KHR_display_swapchain (设备扩展)
//      if (strcmp(ext.extensionName, "VK_KHR_display_swapchain") == 0) {
//        hasDisplaySwapchainExt = true;
//        device_extensions.push_back("VK_KHR_display_swapchain");
//        LOGI("Added device extension: VK_KHR_display_swapchain");
//        break;
//      }
//    }
//  }
//
//  if(!hasDisplaySwapchainExt) {
//    LOGE("VK_KHR_display_swapchain not available on this device (normal for Android)");
//  }
//
//  // 验证设备创建后的功能状态
//  LOGI("=== Device Created Successfully ===");
//  LOGI("Verifying enabled features...");
//
//  // 重新查询已创建设备的功能来验证
//  VkPhysicalDeviceVulkan13Features verifyVulkan13Features{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
//      .pNext = nullptr
//  };
//
//  VkPhysicalDeviceFeatures2 verifyDeviceFeatures2{
//      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
//      .pNext = &verifyVulkan13Features
//  };
//
//  vkGetPhysicalDeviceFeatures2(device.gpuDevice_, &verifyDeviceFeatures2);
//  LOGI("Final privateData support verification: %s", verifyVulkan13Features.privateData ? "ENABLED" : "DISABLED");
//
//  if (!verifyVulkan13Features.privateData) {
//    LOGE("=== Private Data Alternative Solutions ===");
//    LOGE("Since privateData is not supported, consider these alternatives:");
//    LOGE("1. Use application-side hash maps to associate data with Vulkan objects");
//    LOGE("2. Store data in wrapper structures around Vulkan handles");
//    LOGE("3. Use object naming extensions for debugging purposes");
//    LOGE("4. Implement custom object tracking systems");
//  }
//}
//
//void CreateSwapChain(void) {
//  LOGI("->createSwapChain");
//  memset(&swapchain, 0, sizeof(swapchain));
//
//  // **********************************************************
//  // Get the surface capabilities because:
//  //   - It contains the minimal and max length of the chain, we will need it
//  //   - It's necessary to query the supported surface format (R8G8B8A8 for
//  //   instance ...)
//  VkSurfaceCapabilitiesKHR surfaceCapabilities;
//  vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device.gpuDevice_, device.surface_,
//                                            &surfaceCapabilities);
//  // Query the list of supported surface format and choose one we like
//  uint32_t formatCount = 0;
//  vkGetPhysicalDeviceSurfaceFormatsKHR(device.gpuDevice_, device.surface_,
//                                       &formatCount, nullptr);
//  VkSurfaceFormatKHR* formats = new VkSurfaceFormatKHR[formatCount];
//  vkGetPhysicalDeviceSurfaceFormatsKHR(device.gpuDevice_, device.surface_,
//                                       &formatCount, formats);
//  LOGI("Got %d formats", formatCount);
//
//  uint32_t chosenFormat;
//  for (chosenFormat = 0; chosenFormat < formatCount; chosenFormat++) {
//    if (formats[chosenFormat].format == VK_FORMAT_R8G8B8A8_UNORM) break;
//  }
//  assert(chosenFormat < formatCount);
//
//  swapchain.displaySize_ = surfaceCapabilities.currentExtent;
//  swapchain.displayFormat_ = formats[chosenFormat].format;
//
//  // **********************************************************
//  // Create a swap chain (here we choose the minimum available number of surface
//  // in the chain)
//  VkSwapchainCreateInfoKHR swapchainCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
//      .pNext = nullptr,
//      .surface = device.surface_,
//      .minImageCount = surfaceCapabilities.minImageCount,
//      .imageFormat = formats[chosenFormat].format,
//      .imageColorSpace = formats[chosenFormat].colorSpace,
//      .imageExtent = surfaceCapabilities.currentExtent,
//      .imageArrayLayers = 1,
//      .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
//      .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
//      .queueFamilyIndexCount = 1,
//      .pQueueFamilyIndices = &device.queueFamilyIndex_,
//      .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
//      .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
//      .presentMode = VK_PRESENT_MODE_FIFO_KHR,
//      .clipped = VK_FALSE,
//      .oldSwapchain = VK_NULL_HANDLE,
//  };
//  CALL_VK(vkCreateSwapchainKHR(device.device_, &swapchainCreateInfo, nullptr,
//                               &swapchain.swapchain_));
//
//  // Get the length of the created swap chain
//  CALL_VK(vkGetSwapchainImagesKHR(device.device_, swapchain.swapchain_,
//                                  &swapchain.swapchainLength_, nullptr));
//  delete[] formats;
//  LOGI("<-createSwapChain");
//}
//
//void DeleteSwapChain(void) {
//  for (int i = 0; i < swapchain.swapchainLength_; i++) {
//    vkDestroyFramebuffer(device.device_, swapchain.framebuffers_[i], nullptr);
//    vkDestroyImageView(device.device_, swapchain.displayViews_[i], nullptr);
//  }
//  delete[] swapchain.framebuffers_;
//  delete[] swapchain.displayViews_;
//  delete[] swapchain.displayImages_;
//
//  vkDestroySwapchainKHR(device.device_, swapchain.swapchain_, nullptr);
//}
//
//void CreateFrameBuffers(VkRenderPass& renderPass,
//                        VkImageView depthView = VK_NULL_HANDLE) {
//  // query display attachment to swapchain
//  uint32_t SwapchainImagesCount = 0;
//  CALL_VK(vkGetSwapchainImagesKHR(device.device_, swapchain.swapchain_,
//                                  &SwapchainImagesCount, nullptr));
//  swapchain.displayImages_ = new VkImage[SwapchainImagesCount];
//  CALL_VK(vkGetSwapchainImagesKHR(device.device_, swapchain.swapchain_,
//                                  &SwapchainImagesCount,
//                                  swapchain.displayImages_));
//
//  // create image view for each swapchain image
//  swapchain.displayViews_ = new VkImageView[SwapchainImagesCount];
//  for (uint32_t i = 0; i < SwapchainImagesCount; i++) {
//    VkImageViewCreateInfo viewCreateInfo = {
//        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
//        .pNext = nullptr,
//        .flags = 0,
//        .image = swapchain.displayImages_[i],
//        .viewType = VK_IMAGE_VIEW_TYPE_2D,
//        .format = swapchain.displayFormat_,
//        .components =
//            {
//                .r = VK_COMPONENT_SWIZZLE_R,
//                .g = VK_COMPONENT_SWIZZLE_G,
//                .b = VK_COMPONENT_SWIZZLE_B,
//                .a = VK_COMPONENT_SWIZZLE_A,
//            },
//        .subresourceRange =
//            {
//                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
//                .baseMipLevel = 0,
//                .levelCount = 1,
//                .baseArrayLayer = 0,
//                .layerCount = 1,
//            },
//    };
//    CALL_VK(vkCreateImageView(device.device_, &viewCreateInfo, nullptr,
//                              &swapchain.displayViews_[i]));
//  }
//
//  // create a framebuffer from each swapchain image
//  swapchain.framebuffers_ = new VkFramebuffer[swapchain.swapchainLength_];
//  for (uint32_t i = 0; i < swapchain.swapchainLength_; i++) {
//    VkImageView attachments[2] = {
//        swapchain.displayViews_[i], depthView,
//    };
//    VkFramebufferCreateInfo fbCreateInfo{
//        .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
//        .pNext = nullptr,
//        .renderPass = renderPass,
//        .attachmentCount = 1,  // 2 if using depth
//        .pAttachments = attachments,
//        .width = static_cast<uint32_t>(swapchain.displaySize_.width),
//        .height = static_cast<uint32_t>(swapchain.displaySize_.height),
//        .layers = 1,
//    };
//    fbCreateInfo.attachmentCount = (depthView == VK_NULL_HANDLE ? 1 : 2);
//
//    CALL_VK(vkCreateFramebuffer(device.device_, &fbCreateInfo, nullptr,
//                                &swapchain.framebuffers_[i]));
//  }
//}
//
//// A help function to map required memory property into a VK memory type
//// memory type is an index into the array of 32 entries; or the bit index
//// for the memory type ( each BIT of an 32 bit integer is a type ).
//VkResult AllocateMemoryTypeFromProperties(uint32_t typeBits,
//                                          VkFlags requirements_mask,
//                                          uint32_t* typeIndex) {
//  // Search memtypes to find first index with those properties
//  for (uint32_t i = 0; i < 32; i++) {
//    if ((typeBits & 1) == 1) {
//      // Type is available, does it match user properties?
//      if ((device.gpuMemoryProperties_.memoryTypes[i].propertyFlags &
//           requirements_mask) == requirements_mask) {
//        *typeIndex = i;
//        return VK_SUCCESS;
//      }
//    }
//    typeBits >>= 1;
//  }
//  // No memory types matched, return failure
//  return VK_ERROR_MEMORY_MAP_FAILED;
//}
//
//
//VkResult LoadTextureFromFile(const char* filePath,
//                             struct texture_object* tex_obj,
//                             VkImageUsageFlags usage, VkFlags required_props) {
//  if (!(usage | required_props)) {
//    __android_log_print(ANDROID_LOG_ERROR, "tutorial texture",
//                        "No usage and required_pros");
//    return VK_ERROR_FORMAT_NOT_SUPPORTED;
//  }
//
//  // Check for linear supportability
//  VkFormatProperties props;
//  bool needBlit = true;
//  vkGetPhysicalDeviceFormatProperties(device.gpuDevice_, kTexFmt, &props);
//  assert((props.linearTilingFeatures | props.optimalTilingFeatures) &
//         VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
//
//  if (props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
//    // linear format supporting the required texture
//    needBlit = false;
//  }
//
//  // Read the file:
//  AAsset* file = AAssetManager_open(androidAppCtx->activity->assetManager,
//                                    filePath, AASSET_MODE_BUFFER);
//  size_t fileLength = AAsset_getLength(file);
//  stbi_uc* fileContent = new unsigned char[fileLength];
//  AAsset_read(file, fileContent, fileLength);
//  AAsset_close(file);
//
//  uint32_t imgWidth, imgHeight, n;
//  unsigned char* imageData = stbi_load_from_memory(
//      fileContent, fileLength, reinterpret_cast<int*>(&imgWidth),
//      reinterpret_cast<int*>(&imgHeight), reinterpret_cast<int*>(&n), 4);
//  
//  if (n != 4) {
//    // 如果不是 RGBA 格式，手动转换
//    unsigned char* rgbaData = new unsigned char[imgWidth * imgHeight * 4];
//    for (int i = 0; i < imgWidth * imgHeight; i++) {
//        rgbaData[i * 4 + 0] = imageData[i * n + 0];  // R
//        rgbaData[i * 4 + 1] = imageData[i * n + 1];  // G
//        rgbaData[i * 4 + 2] = imageData[i * n + 2];  // B
//        rgbaData[i * 4 + 3] = (n == 3) ? 255 : imageData[i * n + 3];  // A
//    }
//    stbi_image_free(imageData);  // 释放原始数据
//    imageData = rgbaData;        // 替换为 RGBA 数据
//    n = 4;                       // 更新通道数
//  }  
//  assert(n == 4);
//
//  tex_obj->tex_width = imgWidth;
//  tex_obj->tex_height = imgHeight;
//
//  // Allocate the linear texture so texture could be copied over
//  VkImageCreateInfo image_create_info = {
//      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .imageType = VK_IMAGE_TYPE_2D,
//      .format = kTexFmt,
//      .extent = {static_cast<uint32_t>(imgWidth),
//                 static_cast<uint32_t>(imgHeight), 1},
//      .mipLevels = 1,
//      .arrayLayers = 1,
//      .samples = VK_SAMPLE_COUNT_1_BIT,
//      .tiling = VK_IMAGE_TILING_LINEAR,
//      .usage = (needBlit ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT
//                         : VK_IMAGE_USAGE_SAMPLED_BIT),
//      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
//      .queueFamilyIndexCount = 1,
//      .pQueueFamilyIndices = &device.queueFamilyIndex_,
//      .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
//  };
//  VkMemoryAllocateInfo mem_alloc = {
//      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .allocationSize = 0,
//      .memoryTypeIndex = 0,
//  };
//
//  VkMemoryRequirements mem_reqs;
//  CALL_VK(vkCreateImage(device.device_, &image_create_info, nullptr,
//                        &tex_obj->image));
//  vkGetImageMemoryRequirements(device.device_, tex_obj->image, &mem_reqs);
//  mem_alloc.allocationSize = mem_reqs.size;
//  VK_CHECK(AllocateMemoryTypeFromProperties(mem_reqs.memoryTypeBits,
//                                            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
//                                            &mem_alloc.memoryTypeIndex));
//  CALL_VK(vkAllocateMemory(device.device_, &mem_alloc, nullptr, &tex_obj->mem));
//  CALL_VK(vkBindImageMemory(device.device_, tex_obj->image, tex_obj->mem, 0));
//
//  if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
//    const VkImageSubresource subres = {
//        .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = 0, .arrayLayer = 0,
//    };
//    VkSubresourceLayout layout;
//    void* data;
//
//    vkGetImageSubresourceLayout(device.device_, tex_obj->image, &subres,
//                                &layout);
//    CALL_VK(vkMapMemory(device.device_, tex_obj->mem, 0,
//                        mem_alloc.allocationSize, 0, &data));
//
//    for (int32_t y = 0; y < imgHeight; y++) {
//      unsigned char* row = (unsigned char*)((char*)data + layout.rowPitch * y);
//      for (int32_t x = 0; x < imgWidth; x++) {
//        row[x * 4] = imageData[(x + y * imgWidth) * 4];
//        row[x * 4 + 1] = imageData[(x + y * imgWidth) * 4 + 1];
//        row[x * 4 + 2] = imageData[(x + y * imgWidth) * 4 + 2];
//        row[x * 4 + 3] = imageData[(x + y * imgWidth) * 4 + 3];
//      }
//    }
//
//    vkUnmapMemory(device.device_, tex_obj->mem);
//    stbi_image_free(imageData);
//  }
//  delete[] fileContent;
//
//  tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
//
//  VkCommandPoolCreateInfo cmdPoolCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
//      .queueFamilyIndex = device.queueFamilyIndex_,
//  };
//
//  VkCommandPool cmdPool;
//  CALL_VK(vkCreateCommandPool(device.device_, &cmdPoolCreateInfo, nullptr,
//                              &cmdPool));
//
//  VkCommandBuffer gfxCmd;
//  const VkCommandBufferAllocateInfo cmd = {
//      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .commandPool = cmdPool,
//      .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
//      .commandBufferCount = 1,
//  };
//
//  CALL_VK(vkAllocateCommandBuffers(device.device_, &cmd, &gfxCmd));
//  VkCommandBufferBeginInfo cmd_buf_info = {
//      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .pInheritanceInfo = nullptr};
//  CALL_VK(vkBeginCommandBuffer(gfxCmd, &cmd_buf_info));
//
//  // If linear is supported, we are done
//  VkImage stageImage = VK_NULL_HANDLE;
//  VkDeviceMemory stageMem = VK_NULL_HANDLE;
//  if (!needBlit) {
//    setImageLayout(gfxCmd, tex_obj->image, VK_IMAGE_LAYOUT_PREINITIALIZED,
//                   VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
//                   VK_PIPELINE_STAGE_HOST_BIT,
//                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
//  } else {
//    // save current image and mem as staging image and memory
//    stageImage = tex_obj->image;
//    stageMem = tex_obj->mem;
//    tex_obj->image = VK_NULL_HANDLE;
//    tex_obj->mem = VK_NULL_HANDLE;
//
//    // Create a tile texture to blit into
//    image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
//    image_create_info.usage =
//        VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
//    image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
//    CALL_VK(vkCreateImage(device.device_, &image_create_info, nullptr,
//                          &tex_obj->image));
//    vkGetImageMemoryRequirements(device.device_, tex_obj->image, &mem_reqs);
//
//    mem_alloc.allocationSize = mem_reqs.size;
//    VK_CHECK(AllocateMemoryTypeFromProperties(
//        mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
//        &mem_alloc.memoryTypeIndex));
//    CALL_VK(
//        vkAllocateMemory(device.device_, &mem_alloc, nullptr, &tex_obj->mem));
//    CALL_VK(vkBindImageMemory(device.device_, tex_obj->image, tex_obj->mem, 0));
//
//    // transitions image out of UNDEFINED type
//    setImageLayout(gfxCmd, stageImage, VK_IMAGE_LAYOUT_PREINITIALIZED,
//                   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
//                   VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
//    setImageLayout(gfxCmd, tex_obj->image, VK_IMAGE_LAYOUT_UNDEFINED,
//                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
//                   VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
//    VkImageCopy bltInfo{
//        .srcSubresource {
//            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
//            .mipLevel = 0,
//            .baseArrayLayer = 0,
//            .layerCount = 1,
//         },
//        .srcOffset { .x = 0, .y = 0, .z = 0 },
//        .dstSubresource {
//            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
//            .mipLevel = 0,
//            .baseArrayLayer = 0,
//            .layerCount = 1,
//         },
//        .dstOffset { .x = 0, .y = 0, .z = 0},
//        .extent { .width = imgWidth, .height = imgHeight, .depth = 1,},
//    };
//    vkCmdCopyImage(gfxCmd, stageImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
//                   tex_obj->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
//                   &bltInfo);
//
//    setImageLayout(gfxCmd, tex_obj->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
//                   VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
//                   VK_PIPELINE_STAGE_TRANSFER_BIT,
//                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
//  }
//
//  CALL_VK(vkEndCommandBuffer(gfxCmd));
//  VkFenceCreateInfo fenceInfo = {
//      .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//  };
//  VkFence fence;
//  CALL_VK(vkCreateFence(device.device_, &fenceInfo, nullptr, &fence));
//
//  VkSubmitInfo submitInfo = {
//      .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
//      .pNext = nullptr,
//      .waitSemaphoreCount = 0,
//      .pWaitSemaphores = nullptr,
//      .pWaitDstStageMask = nullptr,
//      .commandBufferCount = 1,
//      .pCommandBuffers = &gfxCmd,
//      .signalSemaphoreCount = 0,
//      .pSignalSemaphores = nullptr,
//  };
//  CALL_VK(vkQueueSubmit(device.queue_, 1, &submitInfo, fence) != VK_SUCCESS);
//  CALL_VK(vkWaitForFences(device.device_, 1, &fence, VK_TRUE, 100000000) !=
//          VK_SUCCESS);
//  vkDestroyFence(device.device_, fence, nullptr);
//
//  vkFreeCommandBuffers(device.device_, cmdPool, 1, &gfxCmd);
//  vkDestroyCommandPool(device.device_, cmdPool, nullptr);
//  if (stageImage != VK_NULL_HANDLE) {
//    vkDestroyImage(device.device_, stageImage, nullptr);
//    vkFreeMemory(device.device_, stageMem, nullptr);
//  }
//  return VK_SUCCESS;
//}
//
//void CreateTexture(void) {
//  for (uint32_t i = 0; i < TUTORIAL_TEXTURE_COUNT; i++) {
//    LoadTextureFromFile(texFiles[i], &textures[i], VK_IMAGE_USAGE_SAMPLED_BIT,
//                        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
//
//    const VkSamplerCreateInfo sampler = {
//        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
//        .pNext = nullptr,
//        .magFilter = VK_FILTER_NEAREST,
//        .minFilter = VK_FILTER_NEAREST,
//        .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
//        .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
//        .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
//        .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
//        .mipLodBias = 0.0f,
//        .maxAnisotropy = 1,
//        .compareOp = VK_COMPARE_OP_NEVER,
//        .minLod = 0.0f,
//        .maxLod = 0.0f,
//        .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
//        .unnormalizedCoordinates = VK_FALSE,
//    };
//    VkImageViewCreateInfo view = {
//        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
//        .pNext = nullptr,
//        .flags = 0,
//        .image = VK_NULL_HANDLE,
//        .viewType = VK_IMAGE_VIEW_TYPE_2D,
//        .format = kTexFmt,
//        .components =
//            {
//                VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
//                VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A,
//            },
//        .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
//    };
//
//    CALL_VK(vkCreateSampler(device.device_, &sampler, nullptr,
//                            &textures[i].sampler));
//    view.image = textures[i].image;
//    CALL_VK(
//        vkCreateImageView(device.device_, &view, nullptr, &textures[i].view));
//  }
//}
//
//// A helper function
//bool MapMemoryTypeToIndex(uint32_t typeBits, VkFlags requirements_mask,
//                          uint32_t* typeIndex) {
//  VkPhysicalDeviceMemoryProperties memoryProperties;
//  vkGetPhysicalDeviceMemoryProperties(device.gpuDevice_, &memoryProperties);
//  // Search memtypes to find first index with those properties
//  for (uint32_t i = 0; i < 32; i++) {
//    if ((typeBits & 1) == 1) {
//      // Type is available, does it match user properties?
//      if ((memoryProperties.memoryTypes[i].propertyFlags & requirements_mask) ==
//          requirements_mask) {
//        *typeIndex = i;
//        return true;
//      }
//    }
//    typeBits >>= 1;
//  }
//  return false;
//}
//
//// 从设备读取数据
//void InvalidateBufferData(size_t offset = 0, size_t size = VK_WHOLE_SIZE) {
//  VkMappedMemoryRange invalidateRange{
//      .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
//      .pNext = nullptr,
//      .memory = buffers.memory_,
//      .offset = offset,
//      .size = size
//  };
//  // ========== 测试 vkGetSemaphoreCounterValue ==========
//  LOGI("vkInvalidateMappedMemoryRanges test start");
//  CALL_VK(vkInvalidateMappedMemoryRanges(device.device_, 1, &invalidateRange));
//  LOGI("vkInvalidateMappedMemoryRanges test pass");
//}
//
//// ========== 交互状态与逻辑:start ==========
//// 添加交互状态变量
//struct InteractionState {
//  int currentColorIndex;
//  float currentScale;
//  bool isScaling;
//  float baseScale;
//  float touchStartY;
//  float screenHeight;
//  float screenWidth;
//  
//  // 预定义颜色
//  float colors[5][3] = {
//    {1.0f, 0.0f, 0.0f},  // 红色
//    {0.0f, 1.0f, 0.0f},  // 绿色
//    {0.0f, 0.0f, 1.0f},  // 蓝色
//    {1.0f, 1.0f, 0.0f},  // 黄色
//    {1.0f, 0.0f, 1.0f}   // 紫色
//  };
//  
//  const char* colorNames[5] = {
//    "Red", "Green", "Blue", "Yellow", "Purple"
//  };
//};
//
//static InteractionState interaction;
//
//// 在某个初始化函数中设置默认值，比如在 InitVulkan 开始时
//void InitializeInteractionState() {
//  interaction.currentColorIndex = 0;
//  interaction.currentScale = 1.0f;
//  interaction.isScaling = false;
//  interaction.baseScale = 1.0f;
//  interaction.touchStartY = 0.0f;
//  interaction.screenHeight = 1080.0f;
//  interaction.screenWidth = 1920.0f;
//  
//  // 设置预定义颜色
//  interaction.colors[0][0] = 1.0f; interaction.colors[0][1] = 0.0f; interaction.colors[0][2] = 0.0f; // 红色
//  interaction.colors[1][0] = 0.0f; interaction.colors[1][1] = 1.0f; interaction.colors[1][2] = 0.0f; // 绿色
//  interaction.colors[2][0] = 0.0f; interaction.colors[2][1] = 0.0f; interaction.colors[2][2] = 1.0f; // 蓝色
//  interaction.colors[3][0] = 1.0f; interaction.colors[3][1] = 1.0f; interaction.colors[3][2] = 0.0f; // 黄色
//  interaction.colors[4][0] = 1.0f; interaction.colors[4][1] = 0.0f; interaction.colors[4][2] = 1.0f; // 紫色
//  
//  // 设置颜色名称
//  interaction.colorNames[0] = "Red";
//  interaction.colorNames[1] = "Green";
//  interaction.colorNames[2] = "Blue";
//  interaction.colorNames[3] = "Yellow";
//  interaction.colorNames[4] = "Purple";
//}
//
//// 顶点缓冲区结构体，添加颜色信息
//struct VertexData {
//  float position[3];
//  float texCoord[2];
//  float color[3];  // 添加颜色信息
//};
//
//// 添加交互处理函数
//void ProcessTouchInput(float x, float y, bool isPressed) {
//  if (!IsVulkanReady()) return;
//  
//  LOGI("Touch input: x=%.2f, y=%.2f, pressed=%d", x, y, isPressed);
//  
//  // 更新屏幕尺寸
//  interaction.screenWidth = (float)swapchain.displaySize_.width;
//  interaction.screenHeight = (float)swapchain.displaySize_.height;
//  
//  // 将触摸坐标转换为屏幕坐标比例
//  float normalizedX = x / interaction.screenWidth;
//  float normalizedY = y / interaction.screenHeight;
//  
//  if (isPressed) {
//    // 左半屏：切换颜色
//    if (normalizedX < 0.5f) {
//      interaction.currentColorIndex = (interaction.currentColorIndex + 1) % 5;
//      LOGI("Color changed to: %s", interaction.colorNames[interaction.currentColorIndex]);
//      SetTriangleColor(interaction.currentColorIndex);
//    }
//    // 右半屏：开始缩放
//    else {
//      if (!interaction.isScaling) {  // 只在开始时设置起始点
//        interaction.isScaling = true;
//        interaction.touchStartY = normalizedY;
//        interaction.baseScale = interaction.currentScale;
//        LOGI("Started scaling from: %.2f", interaction.baseScale);
//      }
//    }
//  } else {
//    // 释放触摸时停止缩放
//    if (interaction.isScaling) {
//      interaction.isScaling = false;
//      LOGI("Stopped scaling at: %.2f", interaction.currentScale);
//    }
//  }
//  
//  // 如果正在缩放，更新缩放值
//  if (interaction.isScaling && isPressed) {
//    float deltaY = normalizedY - interaction.touchStartY;
//    float newScale = interaction.baseScale + deltaY * 2.0f;  // 缩放敏感度
//    newScale = fmax(0.1f, fmin(3.0f, newScale));  // 限制缩放范围
//    
//    if (fabs(newScale - interaction.currentScale) > 0.01f) {
//      interaction.currentScale = newScale;
//      SetTriangleScale(newScale);
//      LOGI("Scaling to: %.2f", newScale);
//    }
//  }
//}
//
//void SetTriangleColor(int colorIndex) {
//  if (!IsVulkanReady() || !buffers.mappedData_) return;
//  
//  VertexData* vertices = (VertexData*)buffers.mappedData_;
//  
//  // 更新三个顶点的颜色
//  for (int i = 0; i < 3; i++) {
//    vertices[i].color[0] = interaction.colors[colorIndex][0];
//    vertices[i].color[1] = interaction.colors[colorIndex][1];
//    vertices[i].color[2] = interaction.colors[colorIndex][2];
//  }
//  
//  // 刷新内存
//  VkMappedMemoryRange flushRange{
//      .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
//      .pNext = nullptr,
//      .memory = buffers.memory_,
//      .offset = 0,
//      .size = sizeof(VertexData) * 3
//  };
//  CALL_VK(vkFlushMappedMemoryRanges(device.device_, 1, &flushRange));
//}
//
//void SetTriangleScale(float scale) {
//  // 缩放值将在 VulkanDrawFrame 中应用
//  // 这里只是更新状态
//}
//
//// ========== 交互状态与逻辑:end ==========
//
//
//bool CreateBuffers(void) {
//  // 顶点数据结构，包含位置、纹理坐标和颜色
//  VertexData vertexData[3] = {
//    {{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},  // 红色
//    {{ 0.5f, -0.5f, 0.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},  // 红色
//    {{ 0.0f,  0.5f, 0.0f}, {0.5f, 1.0f}, {1.0f, 0.0f, 0.0f}}   // 红色
//  };
//
//  VkBufferCreateInfo createBufferInfo{
//      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .size = sizeof(vertexData),
//      .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
//      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
//      .queueFamilyIndexCount = 1,
//      .pQueueFamilyIndices = &device.queueFamilyIndex_,
//  };
//
//  CALL_VK(vkCreateBuffer(device.device_, &createBufferInfo, nullptr,
//                         &buffers.vertexBuf_));
//
//  VkMemoryRequirements memReq;
//  vkGetBufferMemoryRequirements(device.device_, buffers.vertexBuf_, &memReq);
//
//  VkMemoryAllocateInfo allocInfo{
//      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .allocationSize = memReq.size,
//      .memoryTypeIndex = 0,
//  };
//
//  MapMemoryTypeToIndex(memReq.memoryTypeBits,
//                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
//                       &allocInfo.memoryTypeIndex);
//
//  CALL_VK(vkAllocateMemory(device.device_, &allocInfo, nullptr, &buffers.memory_));
//  CALL_VK(vkBindBufferMemory(device.device_, buffers.vertexBuf_, buffers.memory_, 0));
//  
//  buffers.mappedData_ = nullptr;
//  VkResult mapResult = vkMapMemory(device.device_, buffers.memory_, 0, allocInfo.allocationSize, 0, &buffers.mappedData_);
//  if (mapResult != VK_SUCCESS || buffers.mappedData_ == nullptr) {
//    LOGE("Failed to map buffer memory");
//    return false;
//  }
//  
//  memcpy(buffers.mappedData_, vertexData, sizeof(vertexData));
//
//  VkMappedMemoryRange flushRange{
//    .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
//    .pNext = nullptr,
//    .memory = buffers.memory_,
//    .offset = 0,
//    .size = sizeof(vertexData)
//  };
//  CALL_VK(vkFlushMappedMemoryRanges(device.device_, 1, &flushRange));
//  
//  return true;
//}
//
//void DeleteBuffers(void) {
//    if (buffers.mappedData_) {
//        vkUnmapMemory(device.device_, buffers.memory_);
//        buffers.mappedData_ = nullptr;
//    }
//    if (buffers.vertexBuf_ != VK_NULL_HANDLE) {
//        vkDestroyBuffer(device.device_, buffers.vertexBuf_, nullptr);
//        buffers.vertexBuf_ = VK_NULL_HANDLE;
//    }
//    if (buffers.memory_ != VK_NULL_HANDLE) {
//        vkFreeMemory(device.device_, buffers.memory_, nullptr);
//        buffers.memory_ = VK_NULL_HANDLE;
//    }
//}
//
//// Create Graphics Pipeline
//VkResult CreateGraphicsPipeline(void) {
//  memset(&gfxPipeline, 0, sizeof(gfxPipeline));
//
//  const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding{
//      .binding = 0,
//      .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
//      .descriptorCount = TUTORIAL_TEXTURE_COUNT,
//      .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
//      .pImmutableSamplers = nullptr,
//  };
//  const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
//      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
//      .pNext = nullptr,
//      .bindingCount = 1,
//      .pBindings = &descriptorSetLayoutBinding,
//  };
//  CALL_VK(vkCreateDescriptorSetLayout(device.device_,
//                                      &descriptorSetLayoutCreateInfo, nullptr,
//                                      &gfxPipeline.dscLayout_));
//  VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
//      .pNext = nullptr,
//      .setLayoutCount = 1,
//      .pSetLayouts = &gfxPipeline.dscLayout_,
//      .pushConstantRangeCount = 0,
//      .pPushConstantRanges = nullptr,
//  };
//  CALL_VK(vkCreatePipelineLayout(device.device_, &pipelineLayoutCreateInfo,
//                                 nullptr, &gfxPipeline.layout_));
//
//  // No dynamic state in that tutorial
//  VkPipelineDynamicStateCreateInfo dynamicStateInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .dynamicStateCount = 0,
//      .pDynamicStates = nullptr};
//
//  VkShaderModule vertexShader, fragmentShader;
//  buildShaderFromFile(androidAppCtx, "shaders/tri.vert",
//                      VK_SHADER_STAGE_VERTEX_BIT, device.device_,
//                      &vertexShader);
//  buildShaderFromFile(androidAppCtx, "shaders/tri.frag",
//                      VK_SHADER_STAGE_FRAGMENT_BIT, device.device_,
//                      &fragmentShader);
//  // Specify vertex and fragment shader stages
//  VkPipelineShaderStageCreateInfo shaderStages[2]{
//      {
//          .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
//          .pNext = nullptr,
//          .flags = 0,
//          .stage = VK_SHADER_STAGE_VERTEX_BIT,
//          .module = vertexShader,
//          .pName = "main",
//          .pSpecializationInfo = nullptr,
//      },
//      {
//          .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
//          .pNext = nullptr,
//          .flags = 0,
//          .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
//          .module = fragmentShader,
//          .pName = "main",
//          .pSpecializationInfo = nullptr,
//      }};
//
//  VkViewport viewports {
//      .x = 0,
//      .y = 0,
//      .width = (float)swapchain.displaySize_.width,
//      .height = (float)swapchain.displaySize_.height,
//      .minDepth = 0.0f,
//      .maxDepth = 1.0f,
//  };
//
//  VkRect2D scissor = {
//          .offset = {.x = 0, .y = 0,},
//          .extent = swapchain.displaySize_,
//   };
//  // Specify viewport info
//  VkPipelineViewportStateCreateInfo viewportInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .viewportCount = 1,
//      .pViewports = &viewports,
//      .scissorCount = 1,
//      .pScissors = &scissor,
//  };
//
//  // Specify multisample info
//  VkSampleMask sampleMask = ~0u;
//  VkPipelineMultisampleStateCreateInfo multisampleInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
//      .sampleShadingEnable = VK_FALSE,
//      .minSampleShading = 0,
//      .pSampleMask = &sampleMask,
//      .alphaToCoverageEnable = VK_FALSE,
//      .alphaToOneEnable = VK_FALSE,
//  };
//
//  // Specify color blend state
//  VkPipelineColorBlendAttachmentState attachmentStates{
//     .blendEnable = VK_FALSE,
//     .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
//                       VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
//  };
//  VkPipelineColorBlendStateCreateInfo colorBlendInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .logicOpEnable = VK_FALSE,
//      .logicOp = VK_LOGIC_OP_COPY,
//      .attachmentCount = 1,
//      .pAttachments = &attachmentStates,
//  };
//
//  // Specify rasterizer info
//  VkPipelineRasterizationStateCreateInfo rasterInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .depthClampEnable = VK_FALSE,
//      .rasterizerDiscardEnable = VK_FALSE,
//      .polygonMode = VK_POLYGON_MODE_FILL,
//      .cullMode = VK_CULL_MODE_NONE,
//      .frontFace = VK_FRONT_FACE_CLOCKWISE,
//      .depthBiasEnable = VK_FALSE,
//      .lineWidth = 1,
//  };
//
//  // Specify input assembler state
//  VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
//      .primitiveRestartEnable = VK_FALSE,
//  };
//
//  // 更新顶点输入绑定描述
//  VkVertexInputBindingDescription vertex_input_bindings{
//      .binding = 0,
//      .stride = sizeof(VertexData),  // 更新步长
//      .inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
//  };
//  
//  // 更新顶点输入属性描述
//  VkVertexInputAttributeDescription vertex_input_attributes[3]{
//      {
//          .location = 0,
//          .binding = 0,
//          .format = VK_FORMAT_R32G32B32_SFLOAT,
//          .offset = offsetof(VertexData, position),
//      },
//      {
//          .location = 1,
//          .binding = 0,
//          .format = VK_FORMAT_R32G32_SFLOAT,
//          .offset = offsetof(VertexData, texCoord),
//      },
//      {
//          .location = 2,  // 新增颜色属性
//          .binding = 0,
//          .format = VK_FORMAT_R32G32B32_SFLOAT,
//          .offset = offsetof(VertexData, color),
//      }
//  };
//  
//  VkPipelineVertexInputStateCreateInfo vertexInputInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
//      .pNext = nullptr,
//      .vertexBindingDescriptionCount = 1,
//      .pVertexBindingDescriptions = &vertex_input_bindings,
//      .vertexAttributeDescriptionCount = 3,  // 更新为3个属性
//      .pVertexAttributeDescriptions = vertex_input_attributes,
//  };
//
//  // Create the pipeline cache
//  VkPipelineCacheCreateInfo pipelineCacheInfo{
//      .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,  // reserved, must be 0
//      .initialDataSize = 0,
//      .pInitialData = nullptr,
//  };
//
//  CALL_VK(vkCreatePipelineCache(device.device_, &pipelineCacheInfo, nullptr,
//                                &gfxPipeline.cache_));
//
//  // Create the pipeline
//  VkGraphicsPipelineCreateInfo pipelineCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .stageCount = 2,
//      .pStages = shaderStages,
//      .pVertexInputState = &vertexInputInfo,
//      .pInputAssemblyState = &inputAssemblyInfo,
//      .pTessellationState = nullptr,
//      .pViewportState = &viewportInfo,
//      .pRasterizationState = &rasterInfo,
//      .pMultisampleState = &multisampleInfo,
//      .pDepthStencilState = nullptr,
//      .pColorBlendState = &colorBlendInfo,
//      .pDynamicState = &dynamicStateInfo,
//      .layout = gfxPipeline.layout_,
//      .renderPass = render.renderPass_,
//      .subpass = 0,
//      .basePipelineHandle = VK_NULL_HANDLE,
//      .basePipelineIndex = 0,
//  };
//
//  VkResult pipelineResult = vkCreateGraphicsPipelines(
//      device.device_, gfxPipeline.cache_, 1, &pipelineCreateInfo, nullptr,
//      &gfxPipeline.pipeline_);
//
//  // We don't need the shaders anymore, we can release their memory
//  vkDestroyShaderModule(device.device_, vertexShader, nullptr);
//  vkDestroyShaderModule(device.device_, fragmentShader, nullptr);
//
//  return pipelineResult;
//}
//
//void DeleteGraphicsPipeline(void) {
//  if (gfxPipeline.pipeline_ == VK_NULL_HANDLE) return;
//  vkDestroyPipeline(device.device_, gfxPipeline.pipeline_, nullptr);
//  vkDestroyPipelineCache(device.device_, gfxPipeline.cache_, nullptr);
//  vkFreeDescriptorSets(device.device_, gfxPipeline.descPool_, 1,
//                       &gfxPipeline.descSet_);
//  vkDestroyDescriptorPool(device.device_, gfxPipeline.descPool_, nullptr);
//  vkDestroyPipelineLayout(device.device_, gfxPipeline.layout_, nullptr);
//}
//
//// initialize descriptor set
//VkResult CreateDescriptorSet(void) {
//  const VkDescriptorPoolSize type_count = {
//      .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
//      .descriptorCount = TUTORIAL_TEXTURE_COUNT,
//  };
//  const VkDescriptorPoolCreateInfo descriptor_pool = {
//      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
//      .pNext = nullptr,
//      .maxSets = 1,
//      .poolSizeCount = 1,
//      .pPoolSizes = &type_count,
//  };
//
//  CALL_VK(vkCreateDescriptorPool(device.device_, &descriptor_pool, nullptr,
//                                 &gfxPipeline.descPool_));
//
//  VkDescriptorSetAllocateInfo alloc_info{
//      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .descriptorPool = gfxPipeline.descPool_,
//      .descriptorSetCount = 1,
//      .pSetLayouts = &gfxPipeline.dscLayout_};
//  CALL_VK(vkAllocateDescriptorSets(device.device_, &alloc_info,
//                                   &gfxPipeline.descSet_));
//
//  VkDescriptorImageInfo texDsts[TUTORIAL_TEXTURE_COUNT];
//  memset(texDsts, 0, sizeof(texDsts));
//  for (int32_t idx = 0; idx < TUTORIAL_TEXTURE_COUNT; idx++) {
//    texDsts[idx].sampler = textures[idx].sampler;
//    texDsts[idx].imageView = textures[idx].view;
//    texDsts[idx].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
//  }
//
//  VkWriteDescriptorSet writeDst{
//      .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
//      .pNext = nullptr,
//      .dstSet = gfxPipeline.descSet_,
//      .dstBinding = 0,
//      .dstArrayElement = 0,
//      .descriptorCount = TUTORIAL_TEXTURE_COUNT,
//      .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
//      .pImageInfo = texDsts,
//      .pBufferInfo = nullptr,
//      .pTexelBufferView = nullptr};
//  vkUpdateDescriptorSets(device.device_, 1, &writeDst, 0, nullptr);
//  return VK_SUCCESS;
//}
//
////======================================================================
//// 创建测试资源
//void CreateTestResources() {
//  LOGI("Creating test resources...");
//  
//  // 创建测试索引缓冲区
//  uint16_t indices[] = {0, 1, 2};
//  VkBufferCreateInfo indexBufferInfo{
//      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .size = sizeof(indices),
//      .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
//      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
//      .queueFamilyIndexCount = 1,
//      .pQueueFamilyIndices = &device.queueFamilyIndex_
//  };
//  
//  CALL_VK(vkCreateBuffer(device.device_, &indexBufferInfo, nullptr, &render.testIndexBuffer_));
//  
//  VkMemoryRequirements indexMemReq;
//  vkGetBufferMemoryRequirements(device.device_, render.testIndexBuffer_, &indexMemReq);
//  
//  VkMemoryAllocateInfo indexAllocInfo{
//      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .allocationSize = indexMemReq.size,
//      .memoryTypeIndex = 0
//  };
//  
//  VK_CHECK(AllocateMemoryTypeFromProperties(indexMemReq.memoryTypeBits,
//                                            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
//                                            &indexAllocInfo.memoryTypeIndex));
//  
//  CALL_VK(vkAllocateMemory(device.device_, &indexAllocInfo, nullptr, &render.testIndexMemory_));
//  CALL_VK(vkBindBufferMemory(device.device_, render.testIndexBuffer_, render.testIndexMemory_, 0));
//  
//  // 初始化索引缓冲区数据
//  void* indexData;
//  CALL_VK(vkMapMemory(device.device_, render.testIndexMemory_, 0, sizeof(indices), 0, &indexData));
//  memcpy(indexData, indices, sizeof(indices));
//  
//  VkMappedMemoryRange indexFlushRange{
//      .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
//      .pNext = nullptr,
//      .memory = render.testIndexMemory_,
//      .offset = 0,
//      .size = sizeof(indices)
//  };
//  CALL_VK(vkFlushMappedMemoryRanges(device.device_, 1, &indexFlushRange));
//  vkUnmapMemory(device.device_, render.testIndexMemory_);
//  
//  // 创建测试拷贝缓冲区
//  VkBufferCreateInfo copyBufferInfo{
//      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .size = 1024,
//      .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
//      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
//      .queueFamilyIndexCount = 1,
//      .pQueueFamilyIndices = &device.queueFamilyIndex_
//  };
//  
//  CALL_VK(vkCreateBuffer(device.device_, &copyBufferInfo, nullptr, &render.testCopyBuffer_));
//  
//  VkMemoryRequirements copyMemReq;
//  vkGetBufferMemoryRequirements(device.device_, render.testCopyBuffer_, &copyMemReq);
//  
//  VkMemoryAllocateInfo copyAllocInfo{
//      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .allocationSize = copyMemReq.size,
//      .memoryTypeIndex = 0
//  };
//  
//  VK_CHECK(AllocateMemoryTypeFromProperties(copyMemReq.memoryTypeBits,
//                                            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
//                                            &copyAllocInfo.memoryTypeIndex));
//  
//  CALL_VK(vkAllocateMemory(device.device_, &copyAllocInfo, nullptr, &render.testCopyMemory_));
//  CALL_VK(vkBindBufferMemory(device.device_, render.testCopyBuffer_, render.testCopyMemory_, 0));
//  
//  // 创建测试图像
//  VkImageCreateInfo imageInfo{
//      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .imageType = VK_IMAGE_TYPE_2D,
//      .format = VK_FORMAT_R8G8B8A8_UNORM,
//      .extent = {256, 256, 1},
//      .mipLevels = 1,
//      .arrayLayers = 1,
//      .samples = VK_SAMPLE_COUNT_1_BIT,
//      .tiling = VK_IMAGE_TILING_OPTIMAL,
//      .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
//      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
//      .queueFamilyIndexCount = 1,
//      .pQueueFamilyIndices = &device.queueFamilyIndex_,
//      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
//  };
//  
//  CALL_VK(vkCreateImage(device.device_, &imageInfo, nullptr, &render.testImage_));
//  
//  VkMemoryRequirements imageMemReq;
//  vkGetImageMemoryRequirements(device.device_, render.testImage_, &imageMemReq);
//  
//  VkMemoryAllocateInfo imageAllocInfo{
//      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .allocationSize = imageMemReq.size,
//      .memoryTypeIndex = 0
//  };
//  
//  VK_CHECK(AllocateMemoryTypeFromProperties(imageMemReq.memoryTypeBits,
//                                            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
//                                            &imageAllocInfo.memoryTypeIndex));
//  
//  CALL_VK(vkAllocateMemory(device.device_, &imageAllocInfo, nullptr, &render.testImageMemory_));
//  CALL_VK(vkBindImageMemory(device.device_, render.testImage_, render.testImageMemory_, 0));
//  
//  // 创建事件
//  VkEventCreateInfo eventInfo{
//      .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0
//  };
//  CALL_VK(vkCreateEvent(device.device_, &eventInfo, nullptr, &render.testEvent_));
//  
//  // 创建查询池
//  VkQueryPoolCreateInfo queryPoolInfo{
//      .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//      .queryType = VK_QUERY_TYPE_TIMESTAMP,
//      .queryCount = 4, // 增加到4个查询用于测试
//      .pipelineStatistics = 0
//  };
//  CALL_VK(vkCreateQueryPool(device.device_, &queryPoolInfo, nullptr, &render.testQueryPool_));
//  
//  LOGI("Test resources created successfully");
//}
//
////==========================================================================
//void LogAvailableExtensions() {
//  LOGI("=== Available Device Extensions ===");
//  
//  uint32_t extensionCount = 0;
//  vkEnumerateDeviceExtensionProperties(device.gpuDevice_, nullptr, &extensionCount, nullptr);
//  
//  if (extensionCount > 0) {
//    std::vector<VkExtensionProperties> extensions(extensionCount);
//    vkEnumerateDeviceExtensionProperties(device.gpuDevice_, nullptr, &extensionCount, extensions.data());
//    
//    LOGI("Total extensions: %d", extensionCount);
//    for (const auto& ext : extensions) {
//      LOGI("  - %s (version %d)", ext.extensionName, ext.specVersion);
//    }
//  }
//  
//  LOGI("=== End Extensions List ===");
//}
//
//
//// InitVulkan:
////   Initialize Vulkan Context when android application window is created
////   upon return, vulkan is ready to draw frames
//bool InitVulkan(android_app* app) {
//  androidAppCtx = app;
//
//  // 初始化交互状态
//  InitializeInteractionState();
//
//  if (!InitVulkan()) {
//    LOGW("Vulkan is unavailable, install vulkan and re-start");
//    return false;
//  }
//
//  VkApplicationInfo appInfo = {
//      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
//      .pNext = nullptr,
//      .pApplicationName = "tutorial05_triangle_window",
//     .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
//      .pEngineName = "tutorial",
//     .engineVersion = VK_MAKE_VERSION(1, 0, 0),
//     .apiVersion = VK_MAKE_VERSION(1, 3, 0),
//  };
//
//  uint32_t instanceVersion = 0;
//  PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion = 
//      (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion");
//  
//  if (pfn_vkEnumerateInstanceVersion) {
//      VkResult result = pfn_vkEnumerateInstanceVersion(&instanceVersion);
//      if (result == VK_SUCCESS) {
//          LOGI("Instance supports Vulkan %u.%u.%u", 
//               VK_VERSION_MAJOR(instanceVersion),
//               VK_VERSION_MINOR(instanceVersion), 
//               VK_VERSION_PATCH(instanceVersion));
//          
//          // 使用支持的最高版本，但不超过1.3
//          if (VK_VERSION_MAJOR(instanceVersion) >= 1 && VK_VERSION_MINOR(instanceVersion) >= 3) {
//              appInfo.apiVersion = VK_MAKE_VERSION(1, 3, 0);
//              LOGI("Requesting Vulkan 1.3 for privateData support");
//          } else {
//              appInfo.apiVersion = instanceVersion;
//              LOGI("Using maximum supported version");
//          }
//      }
//  } else {
//      LOGI("vkEnumerateInstanceVersion not available, using Vulkan 1.0");
//      appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0);
//  }
//
//  // create a device
//  CreateVulkanDevice(app->window, &appInfo);
//  CreateSwapChain();
//
//  // Create render pass
//  VkAttachmentDescription attachmentDescriptions{
//      .format = swapchain.displayFormat_,
//      .samples = VK_SAMPLE_COUNT_1_BIT,
//      .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
//      .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
//      .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
//      .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
//      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
//      .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
//  };
//
//  VkAttachmentReference colourReference = {
//      .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
//
//  VkSubpassDescription subpassDescription{
//      .flags = 0,
//      .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
//      .inputAttachmentCount = 0,
//      .pInputAttachments = nullptr,
//      .colorAttachmentCount = 1,
//      .pColorAttachments = &colourReference,
//      .pResolveAttachments = nullptr,
//      .pDepthStencilAttachment = nullptr,
//      .preserveAttachmentCount = 0,
//      .pPreserveAttachments = nullptr,
//  };
//  
//  VkRenderPassCreateInfo renderPassCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
//      .pNext = nullptr,
//      .attachmentCount = 1,
//      .pAttachments = &attachmentDescriptions,
//      .subpassCount = 1,
//      .pSubpasses = &subpassDescription,
//      .dependencyCount = 0,
//      .pDependencies = nullptr,
//  };
//  CALL_VK(vkCreateRenderPass(device.device_, &renderPassCreateInfo, nullptr,
//                             &render.renderPass_));
//
//  CreateFrameBuffers(render.renderPass_);
//  CreateTexture();
//  CreateBuffers();
//  CreateTestResources();
//  CreateGraphicsPipeline();
//  CreateDescriptorSet();
//
//  // Create command pool and buffers
//  VkCommandPoolCreateInfo cmdPoolCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
//      .queueFamilyIndex = 0,
//  };
//  CALL_VK(vkCreateCommandPool(device.device_, &cmdPoolCreateInfo, nullptr,
//                              &render.cmdPool_));
//
//  render.cmdBufferLen_ = swapchain.swapchainLength_;
//  render.cmdBuffer_ = new VkCommandBuffer[swapchain.swapchainLength_];
//  VkCommandBufferAllocateInfo cmdBufferCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
//      .pNext = nullptr,
//      .commandPool = render.cmdPool_,
//      .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
//      .commandBufferCount = render.cmdBufferLen_,
//  };
//  CALL_VK(vkAllocateCommandBuffers(device.device_, &cmdBufferCreateInfo,
//                                   render.cmdBuffer_));
//
//  // Record command buffers
//  for (int bufferIndex = 0; bufferIndex < swapchain.swapchainLength_; bufferIndex++) {
//    VkCommandBufferBeginInfo cmdBufferBeginInfo{
//        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
//        .pNext = nullptr,
//        .flags = 0,
//        .pInheritanceInfo = nullptr,
//    };
//    CALL_VK(vkBeginCommandBuffer(render.cmdBuffer_[bufferIndex], &cmdBufferBeginInfo));
//
//    setImageLayout(render.cmdBuffer_[bufferIndex],
//                   swapchain.displayImages_[bufferIndex],
//                   VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
//                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
//                   VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
//                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
//
//    VkClearValue clearVals{
//        .color { .float32 { 0.0f, 0.34f, 0.90f, 1.0f,}},
//    };
//
//    VkRenderPassBeginInfo renderPassBeginInfo{
//        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
//        .pNext = nullptr,
//        .renderPass = render.renderPass_,
//        .framebuffer = swapchain.framebuffers_[bufferIndex],
//        .renderArea = {.offset = {.x = 0, .y = 0,}, .extent = swapchain.displaySize_},
//        .clearValueCount = 1,
//        .pClearValues = &clearVals
//    };
//    vkCmdBeginRenderPass(render.cmdBuffer_[bufferIndex], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
//
//    vkCmdBindPipeline(render.cmdBuffer_[bufferIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, gfxPipeline.pipeline_);
//    vkCmdBindDescriptorSets(render.cmdBuffer_[bufferIndex], VK_PIPELINE_BIND_POINT_GRAPHICS,
//                           gfxPipeline.layout_, 0, 1, &gfxPipeline.descSet_, 0, nullptr);
//    VkDeviceSize offset = 0;
//    vkCmdBindVertexBuffers(render.cmdBuffer_[bufferIndex], 0, 1, &buffers.vertexBuf_, &offset);
//
//    vkCmdDraw(render.cmdBuffer_[bufferIndex], 3, 1, 0, 0);
//    vkCmdEndRenderPass(render.cmdBuffer_[bufferIndex]);
//
//    setImageLayout(render.cmdBuffer_[bufferIndex],
//                   swapchain.displayImages_[bufferIndex],
//                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
//                   VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
//                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
//                   VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
//    CALL_VK(vkEndCommandBuffer(render.cmdBuffer_[bufferIndex]));
//  }
//
//  // Create synchronization objects
//  VkFenceCreateInfo fenceCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//  };
//  CALL_VK(vkCreateFence(device.device_, &fenceCreateInfo, nullptr, &render.fence_));
//
//  VkSemaphoreCreateInfo semaphoreCreateInfo{
//      .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
//      .pNext = nullptr,
//      .flags = 0,
//  };
//  CALL_VK(vkCreateSemaphore(device.device_, &semaphoreCreateInfo, nullptr,
//                            &render.semaphore_));
//
//  device.initialized_ = true;
//
//  return true;
//}
//
//// IsVulkanReady():
////    native app poll to see if we are ready to draw...
//bool IsVulkanReady(void) { return device.initialized_; }
//
//void DeleteVulkan() {
//  // 等待设备空闲，确保所有操作完成
//  if (device.device_ != VK_NULL_HANDLE) {
//    vkDeviceWaitIdle(device.device_);
//  }
//  
//  // 清理测试资源
//  if (render.testComputePipeline_ != VK_NULL_HANDLE) {
//    vkDestroyPipeline(device.device_, render.testComputePipeline_, nullptr);
//    render.testComputePipeline_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testComputePipelineLayout_ != VK_NULL_HANDLE) {
//    vkDestroyPipelineLayout(device.device_, render.testComputePipelineLayout_, nullptr);
//    render.testComputePipelineLayout_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testComputeShaderModule_ != VK_NULL_HANDLE) {
//    vkDestroyShaderModule(device.device_, render.testComputeShaderModule_, nullptr);
//    render.testComputeShaderModule_ = VK_NULL_HANDLE;
//  }
//
//  if (render.testDescriptorUpdateTemplate_ != VK_NULL_HANDLE) {
//    vkDestroyDescriptorUpdateTemplate(device.device_, render.testDescriptorUpdateTemplate_, nullptr);
//    render.testDescriptorUpdateTemplate_ = VK_NULL_HANDLE;
//  }
//
//  if (render.testPrivateDataSlot_ != VK_NULL_HANDLE) {
//    vkDestroyPrivateDataSlot(device.device_, render.testPrivateDataSlot_, nullptr);
//    render.testPrivateDataSlot_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testRenderPass2_ != VK_NULL_HANDLE) {
//    vkDestroyRenderPass(device.device_, render.testRenderPass2_, nullptr);
//    render.testRenderPass2_ = VK_NULL_HANDLE;
//  }
//
//  if (render.testYcbcrConversion_ != VK_NULL_HANDLE) {
//    vkDestroySamplerYcbcrConversion(device.device_, render.testYcbcrConversion_, nullptr);
//    render.testYcbcrConversion_ = VK_NULL_HANDLE;
//  }
//  if (render.testIndexBuffer_ != VK_NULL_HANDLE) {
//    vkDestroyBuffer(device.device_, render.testIndexBuffer_, nullptr);
//    render.testIndexBuffer_ = VK_NULL_HANDLE;
//  }
//  if (render.testIndexMemory_ != VK_NULL_HANDLE) {
//    vkFreeMemory(device.device_, render.testIndexMemory_, nullptr);
//    render.testIndexMemory_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testCopyBuffer_ != VK_NULL_HANDLE) {
//    vkDestroyBuffer(device.device_, render.testCopyBuffer_, nullptr);
//    render.testCopyBuffer_ = VK_NULL_HANDLE;
//  }
//  if (render.testCopyMemory_ != VK_NULL_HANDLE) {
//    vkFreeMemory(device.device_, render.testCopyMemory_, nullptr);
//    render.testCopyMemory_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testImage_ != VK_NULL_HANDLE) {
//    vkDestroyImage(device.device_, render.testImage_, nullptr);
//    render.testImage_ = VK_NULL_HANDLE;
//  }
//  if (render.testImageMemory_ != VK_NULL_HANDLE) {
//    vkFreeMemory(device.device_, render.testImageMemory_, nullptr);
//    render.testImageMemory_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testEvent_ != VK_NULL_HANDLE) {
//    vkDestroyEvent(device.device_, render.testEvent_, nullptr);
//    render.testEvent_ = VK_NULL_HANDLE;
//  }
//  
//  if (render.testQueryPool_ != VK_NULL_HANDLE) {
//      vkDestroyQueryPool(device.device_, render.testQueryPool_, nullptr);
//      render.testQueryPool_ = VK_NULL_HANDLE;
//  }
//
//  
//  // 清理同步对象
//  if (render.semaphore_ != VK_NULL_HANDLE) {
//    vkDestroySemaphore(device.device_, render.semaphore_, nullptr);
//    render.semaphore_ = VK_NULL_HANDLE;
//  }
//  if (render.fence_ != VK_NULL_HANDLE) {
//    vkDestroyFence(device.device_, render.fence_, nullptr);
//    render.fence_ = VK_NULL_HANDLE;
//  }
//  
//  // 清理命令缓冲区和命令池
//  if (render.cmdBuffer_ != nullptr && render.cmdPool_ != VK_NULL_HANDLE) {
//    vkFreeCommandBuffers(device.device_, render.cmdPool_, render.cmdBufferLen_,
//                         render.cmdBuffer_);
//    delete[] render.cmdBuffer_;
//    render.cmdBuffer_ = nullptr;
//  }
//  
//  if (render.cmdPool_ != VK_NULL_HANDLE) {
//    vkDestroyCommandPool(device.device_, render.cmdPool_, nullptr);
//    render.cmdPool_ = VK_NULL_HANDLE;
//  }
//  
//  // 清理渲染通道
//  if (render.renderPass_ != VK_NULL_HANDLE) {
//    vkDestroyRenderPass(device.device_, render.renderPass_, nullptr);
//    render.renderPass_ = VK_NULL_HANDLE;
//  }
//  
//  
//  // 清理交换链
//  DeleteSwapChain();
//  
//  // 清理图形管线
//  DeleteGraphicsPipeline();
//  
//  // 清理描述符集布局（如果 DeleteGraphicsPipeline 中没有清理）
//  if (gfxPipeline.dscLayout_ != VK_NULL_HANDLE) {
//    vkDestroyDescriptorSetLayout(device.device_, gfxPipeline.dscLayout_, nullptr);
//    gfxPipeline.dscLayout_ = VK_NULL_HANDLE;
//  }
//  
//  // 清理纹理资源
//  for (uint32_t i = 0; i < TUTORIAL_TEXTURE_COUNT; i++) {
//    if (textures[i].sampler != VK_NULL_HANDLE) {
//      vkDestroySampler(device.device_, textures[i].sampler, nullptr);
//      textures[i].sampler = VK_NULL_HANDLE;
//    }
//    if (textures[i].view != VK_NULL_HANDLE) {
//      vkDestroyImageView(device.device_, textures[i].view, nullptr);
//      textures[i].view = VK_NULL_HANDLE;
//    }
//    if (textures[i].image != VK_NULL_HANDLE) {
//      vkDestroyImage(device.device_, textures[i].image, nullptr);
//      textures[i].image = VK_NULL_HANDLE;
//    }
//    if (textures[i].mem != VK_NULL_HANDLE) {
//      vkFreeMemory(device.device_, textures[i].mem, nullptr);
//      textures[i].mem = VK_NULL_HANDLE;
//    }
//  }
//  
//  // 清理缓冲区
//  DeleteBuffers();
//  
//  // 清理表面
//  if (device.surface_ != VK_NULL_HANDLE) {
//    vkDestroySurfaceKHR(device.instance_, device.surface_, nullptr);
//    device.surface_ = VK_NULL_HANDLE;
//  }
//  
//  // 清理设备
//  if (device.device_ != VK_NULL_HANDLE) {
//    vkDestroyDevice(device.device_, nullptr);
//    device.device_ = VK_NULL_HANDLE;
//  }
//  
//  // 清理实例
//  if (device.instance_ != VK_NULL_HANDLE) {
//    vkDestroyInstance(device.instance_, nullptr);
//    device.instance_ = VK_NULL_HANDLE;
//  }
//    
//  // 重置设备状态
//  device.initialized_ = false;
//  
//  LOGI("Vulkan cleanup completed");
//}
//
//// Draw one frame
//bool VulkanDrawFrame(void) {
//  static float angle = 0.0f;
//  angle += 0.01f;
//
//  // 应用旋转和缩放
//  float cosTheta = cos(angle);
//  float sinTheta = sin(angle);
//  float scale = interaction.currentScale;
//  
//  VertexData newVertexData[3];
//  
//  // 基本三角形顶点
//  float baseVertices[3][2] = {
//    {-0.5f, -0.5f},
//    { 0.5f, -0.5f},
//    { 0.0f,  0.5f}
//  };
//  
//  for (int i = 0; i < 3; i++) {
//    // 应用缩放
//    float scaledX = baseVertices[i][0] * scale;
//    float scaledY = baseVertices[i][1] * scale;
//    
//    // 应用旋转
//    newVertexData[i].position[0] = scaledX * cosTheta - scaledY * sinTheta;
//    newVertexData[i].position[1] = scaledX * sinTheta + scaledY * cosTheta;
//    newVertexData[i].position[2] = 0.0f;
//    
//    // 纹理坐标
//    newVertexData[i].texCoord[0] = (i == 0) ? 0.0f : (i == 1) ? 1.0f : 0.5f;
//    newVertexData[i].texCoord[1] = (i == 2) ? 1.0f : 0.0f;
//    
//    // 当前颜色
//    newVertexData[i].color[0] = interaction.colors[interaction.currentColorIndex][0];
//    newVertexData[i].color[1] = interaction.colors[interaction.currentColorIndex][1];
//    newVertexData[i].color[2] = interaction.colors[interaction.currentColorIndex][2];
//  }
//  
//  memcpy(buffers.mappedData_, newVertexData, sizeof(newVertexData));
//
//  VkMappedMemoryRange flushRange{
//      .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
//      .pNext = nullptr,
//      .memory = buffers.memory_,
//      .offset = 0,
//      .size = sizeof(newVertexData)
//  };
//  CALL_VK(vkFlushMappedMemoryRanges(device.device_, 1, &flushRange));
//
//  uint32_t nextIndex;
//  CALL_VK(vkAcquireNextImageKHR(device.device_, swapchain.swapchain_,
//                                UINT64_MAX, render.semaphore_, VK_NULL_HANDLE,
//                                &nextIndex));
//  CALL_VK(vkResetFences(device.device_, 1, &render.fence_));
//
//  VkPipelineStageFlags waitStageMask =
//      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
//  VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
//                              .pNext = nullptr,
//                              .waitSemaphoreCount = 1,
//                              .pWaitSemaphores = &render.semaphore_,
//                              .pWaitDstStageMask = &waitStageMask,
//                              .commandBufferCount = 1,
//                              .pCommandBuffers = &render.cmdBuffer_[nextIndex],
//                              .signalSemaphoreCount = 0,
//                              .pSignalSemaphores = nullptr};
//  CALL_VK(vkQueueSubmit(device.queue_, 1, &submit_info, render.fence_));
//  CALL_VK(vkWaitForFences(device.device_, 1, &render.fence_, VK_TRUE, 100000000));
//
//  VkResult result;
//  VkPresentInfoKHR presentInfo{
//      .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
//      .pNext = nullptr,
//      .waitSemaphoreCount = 0,
//      .pWaitSemaphores = nullptr,
//      .swapchainCount = 1,
//      .pSwapchains = &swapchain.swapchain_,
//      .pImageIndices = &nextIndex,
//      .pResults = &result,
//  };
//  vkQueuePresentKHR(device.queue_, &presentInfo);
//  return true;
//}
//
//void setImageLayout(VkCommandBuffer cmdBuffer, VkImage image,
//                    VkImageLayout oldImageLayout, VkImageLayout newImageLayout,
//                    VkPipelineStageFlags srcStages,
//                    VkPipelineStageFlags destStages) {
//  VkImageMemoryBarrier imageMemoryBarrier = {
//      .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
//      .pNext = NULL,
//      .srcAccessMask = 0,
//      .dstAccessMask = 0,
//      .oldLayout = oldImageLayout,
//      .newLayout = newImageLayout,
//      .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
//      .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
//      .image = image,
//      .subresourceRange =
//          {
//              .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
//              .baseMipLevel = 0,
//              .levelCount = 1,
//              .baseArrayLayer = 0,
//              .layerCount = 1,
//          },
//  };
//
//  switch (oldImageLayout) {
//    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
//      imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
//      break;
//
//    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
//      imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
//      break;
//
//    case VK_IMAGE_LAYOUT_PREINITIALIZED:
//      imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
//      break;
//
//    default:
//      break;
//  }
//
//  switch (newImageLayout) {
//    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
//      imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
//      break;
//
//    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
//      imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
//      break;
//
//    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
//      imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
//      break;
//
//    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
//      imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
//      break;
//
//    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
//      imageMemoryBarrier.dstAccessMask =
//          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
//      break;
//
//    default:
//      break;
//  }
//
//  vkCmdPipelineBarrier(cmdBuffer, srcStages, destStages, 0, 0, NULL, 0, NULL, 1,
//                       &imageMemoryBarrier);
//}
